﻿using MathNet.Numerics;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace PumpAlgorithm.Standard
{
    public class ScrewPumpPerf
    {
        
            #region 标准判断
        /*
            private static Double getPressureLevelValue(Double pressure, int level)
            {
              return 1.0;
            }

            /// <summary>
            /// 根据流量值获取lewel级别下该值的范围
            /// </summary>
            /// <param name="flow">输入的流量</param>
            /// <param name="level">输入级别</param>
            /// <returns></returns>
            private static Double[] getFlowLevelValue(Double flow, int level)
            {
                if (( 0.1- flow) > Double.Epsilon)
                {
                    if (level==1)
                    {
                        return new double[] { 10.0, 10.0 };
                    }
                    else if (level==2)
                    {
                        return new double[] { 20.0, 10 };
                    }
                }
                else if ((flow - 0.1) > Double.Epsilon && (10 - flow) > Double.Epsilon)
                {
                    if (level==1)
                    {
                        return new double[] { 5, 5 };
                    }
                    else if (level==2)
                    {
                        return new double[] { 10,10 };
                    }
                }
                else if ((flow - 10) > Double.Epsilon)
                {
                    if (level==1)
                    {
                        return new double[] { 5, 5 };
                    }
                    else if (level==2)
                    {
                        return new double[] { 10,5 };
                    }
                }
                return null;
            }

            /// <summary>
            /// 根据功率值获取level下该值的范围
            /// </summary>
            /// <param name="power">输入的功率</param>
            /// <param name="level">输入的级别</param>
            /// <returns></returns>
            private static Double getPowerLevelValue(Double power,int level)
            {
                if ((5 - power) > Double.Epsilon)
                {
                    return 25.0;
                }
                else if ((power - 5) > Double.Epsilon && (10 - power) > Double.Epsilon)
                {
                    if (level.Equals("1"))
                    {
                        return 15.0;
                    }
                    else if (level.Equals("2"))
                    {
                        return 20.0;
                    }
                }
                else if ((power - 10) > Double.Epsilon && (50 - power) > Double.Epsilon)
                {
                    if (level.Equals("1"))
                    {
                        return 10.0;
                    }
                    else if (level.Equals("2"))
                    {
                        return 15.0;
                    }
                }
                else if ((power - 50) > Double.Epsilon)
                {
                    if (level.Equals("1"))
                    {
                        return 5.0;
                    }
                    else if (level.Equals("2"))
                    {
                        return 10.0;
                    }
                }
                return double.NaN;   
            }

            /// <summary>
            /// 获取指定效率在对应的level下的取值范围
            /// </summary>
            /// <param name="rateEff">效率</param>
            /// <param name="level">取值范围，是一个指定的数值</param>
            /// <returns></returns>
            private static double getEffLevelValue(double rateEff, int level)
                {
            return 5.0;
                }

                double startValue = minPresure;
                double endValue = maxPresure;

                //最大的额定流量算出的扬程还大于额定流量的话，说明不会找到焦点

                int caculateCount = 0;
                int seg = 10;
                do
                {
                    for (int i = 0; i < seg; i++)
                    {
                        double segValue = startValue + ((endValue - startValue) / seg) * i;

                        double curveFlow = CanonicalAlgorithm.CaculateValue(segValue, paramQ);
                        double segValueEnd = startValue + ((endValue - startValue) / seg) * (i + 1);
                        double curveFlowEnd = CanonicalAlgorithm.CaculateValue(segValueEnd, paramQ);
                    
                        if (Math.Abs(curveFlow - flow) < 0.00001)
                        {
                            double[] ret = new double[] { segValue, curveFlow };
                            return ret;
                        }

                        if ((curveFlow - flow > Double.Epsilon) && (flow - curveFlowEnd > Double.Epsilon))
                        {
                            startValue = segValue;
                            endValue = segValueEnd;
                            break;
                        }
                    }
                    caculateCount++;

                } while (caculateCount <= 15);
                return null;
            }

            /// <summary>
            /// 流量标准判断
            /// </summary>
            /// <param name="head">计算流量</param>
            /// <param name="ratedHead">额定流量</param>
            /// <param name="level">判断等级</param>
            /// <returns></returns>
            public static Boolean JudgeFlowLevel(Double flow, Double ratedFlow, int level)
            {
                Double[] rate = getFlowLevelValue(flow, level);
                if (((ratedFlow * (100 + rate[0]) / 100.0f) - ratedFlow) > Double.Epsilon && (flow - (ratedFlow * (100 - rate[1]) / 100.0f) > Double.Epsilon))
                {
                    return true;
                }
                return false;

        }

            /// <summary>
        /// 功率标准判断
        /// </summary>
        /// <param name="power">功率</param>
        /// <param name="ratedPower">额定功率</param>
        /// <param name="level">等级</param>
        /// <returns></returns>
            public static Boolean JudgePowerLevel(Double power, Double ratedPower, int level)
            {
                double rate = getPowerLevelValue(power, level);
                if (((ratedPower * (100 + rate) / 100.0f) - power) > Double.Epsilon)
                {
                    return true;
                 }
                 return false;
            }
            */
            

     
            /// <summary>
            /// 找出拟合的曲线与额定压力，额定流量之间的关系
            /// </summary>
            /// <param name="ratedPresure"></param>
            /// <param name="ratedFlow"></param>
            /// <param name="maxPresure"></param>
            /// <param name="paramQ"></param>
            /// <returns></returns>
        public static double[] CaculateCrossPresureFlow(Double ratedPresure, Double ratedFlow,Double minPresure,Double maxPresure, Double[] paramQ)
            {
                double rate = ratedFlow / ratedPresure;

                int seg = 10;
                double startValue = 0;
                double endValue = maxPresure;

                //最大的额定流量算出的扬程还大于额定流量的话，说明不会找到焦点
                if (CanonicalAlgorithm.CaculateValue(maxPresure, paramQ) - ratedFlow > Double.Epsilon)
                {
                    return null;
                }

            double[] result = CanonicalAlgorithm.SolveEquations(new double[] { paramQ[0],paramQ[1],paramQ[2],paramQ[3]-(ratedFlow/ratedPresure),paramQ[4]});

            List<double> list = new List<double>();
            if (result != null)
            {
                for (int i = 0; i < result.Length && (result[i] - minPresure) > double.Epsilon && maxPresure - result[i] > double.Epsilon; i++)
                {
                    list.Add(result[i]);
                }
            }
            if (list.Count > 1)
            {
                throw new Exception("方程有超过两个合理的解，请检查曲线是否合理!");
            }
            else if (list.Count == 0)
            {
                return null;
            }
            else
            {
                double x = result[0];
                double y = (ratedFlow / ratedPresure) * x;
                return new double[] { x, y };
            }

            /*

                int caculateCount = 0;


                do
                {

                    for (int i = 0; i < seg; i++)
                    {
                        double segValue = startValue + ((endValue - startValue) / seg) * i;

                        double curveFlow = CanonicalAlgorithm.CaculateValue(segValue, paramQ);
                        double segValueEnd = startValue + ((endValue - startValue) / seg) * (i + 1);
                        double curveFlowEnd = CanonicalAlgorithm.CaculateValue(segValueEnd, paramQ);
                        //double deltaMax = caculateValue(segMax, paramH)-rate* segMax;
                        if (Math.Abs(curveFlow - ratedFlow) < 0.00001)
                        {
                            double[] ret = new double[] { segValue, curveFlow };
                            return ret;
                        }

                        if ((curveFlow - ratedFlow > Double.Epsilon) && (ratedFlow - curveFlowEnd > Double.Epsilon))
                        {
                            startValue = segValue;
                            endValue = segValueEnd;
                            break;
                        }
                    }
                    caculateCount++;

                } while (caculateCount <= 10);
                return null;
                */
            }

        /// <summary>
        /// 解方程，用拟合公式求额定流量下的压力值，目前该函数未使用
        /// </summary>
        /// <param name="paramH"></param>
        /// <param name="head"></param>
        /// <param name="minQ"></param>
        /// <param name="maxQ"></param>
        /// <returns></returns>
        public static Double[] CaculateResultFlowValue(Double[] paramQ, Double flow, Double minPresure, Double maxPresure)
        {
            Double maxFlow = CanonicalAlgorithm.CaculateValue(minPresure, paramQ);
            Double minFlow = CanonicalAlgorithm.CaculateValue(maxPresure, paramQ);

            if (flow - maxFlow > Double.Epsilon || minFlow - flow > Double.Epsilon)
            {
                return null;
            }

            double startValue = minPresure;
            double endValue = maxPresure;

            //最大的额定流量算出的扬程还大于额定流量的话，说明不会找到焦点
 
            int caculateCount = 0;
            int seg = 10;
            do
            {
                for (int i = 0; i < seg; i++)
                {
                    double segValue = startValue + ((endValue - startValue) / seg) * i;

                    double curveFlow = CanonicalAlgorithm.CaculateValue(segValue, paramQ);
                    double segValueEnd = startValue + ((endValue - startValue) / seg) * (i + 1);
                    double curveFlowEnd = CanonicalAlgorithm.CaculateValue(segValueEnd, paramQ);

                    if (Math.Abs(curveFlow - flow) < 0.00001)
            {
                        double[] ret = new double[] { segValue, curveFlow };
                        return ret;
                    }

                    if ((curveFlow - flow > Double.Epsilon) && (flow - curveFlowEnd > Double.Epsilon))
                {
                        startValue = segValue;
                        endValue = segValueEnd;
                        break;
                    }
                }
                caculateCount++;

            } while (caculateCount <= 15);
            return null;
            }

        

        /*
                   /// <summary>
               /// 根据额定流量，计算出工况流量在level上的允许范围，支持上下界值。
               /// </summary>
               /// <param name="ratedFlow">根据额定压力代入工况下的压力流量曲线计算出来的流量</param>
               /// <param name="level">预期的level</param>
               /// <returns>返回工况流量在level上的允许范围，支持上下界值。</returns>
        public static double[] GetFlowRange(double ratedFlow,int level)
        {
            double[] flowRate = getFlowLevelValue(ratedFlow, level);
            return new double[]
            {
                ratedFlow*(1+flowRate[0]/100.0),ratedFlow*(1-flowRate[1]/100.0)
            };
        }

        public static double GetPowerRange(double ratedPower, int level)
        {
            double powerRate = getPowerLevelValue(ratedPower/1000.0, level);
            return ratedPower * (1 + powerRate/100.0);

        }

        public static double GetEffRange(double rateEff, int level)
        {
            double effRate = getEffLevelValue(rateEff, level);
            return rateEff * (1 - effRate/100.0);  
        }
               */
        #endregion

        #region 注释内容
        /*

         /// <summary>
         /// 根据标准设置流量，养成的范围
         /// </summary>
         /// <param name="flow"></param>
         /// <param name="head"></param>
         /// <param name="level"></param>
         /// <returns></returns>
         public static Double[,] GetPresureFlowRange(Double presure, Double flow, String level)
         {
             int flowRate = (int)flowLevelTable[level];
             int headHead = (int)headLevelTable[level];


             double startFlow = flow * (1.0f - flowRate / 100.0f);
             double endFlow = flow * (1.0f + flowRate / 100.0f);

             double startHead = head * (1.0f - headHead / 100.0f);
             double endHead = head * (1.0f + headHead / 100.0f);

             Double[,] ret = new Double[4, 2]
             {
             { startFlow, head },
             { endFlow,   head },
             { flow,      startHead},
             { flow,      endHead}
             };
             return ret;
         }

         public static Double[,] GetPresurePowerRange(Double flow, Double power, String level)
         {
             int flowRate = (int)flowLevelTable[level];
             int powerRate = (int)powerLevelTable[level];


             double startFlow = flow * (1.0f - flowRate / 100.0f);
             double endFlow = flow * (1.0f + flowRate / 100.0f);

             double startPower = power;
             double endPower = power * (1.0f + powerRate / 100.0f);

             Double[,] ret = new Double[4, 2]
             {
             { startFlow, power },
             { endFlow,   power },
             { flow,      startPower},
             { flow,      endPower}
             };
             return ret;
         }
        */
        #endregion


    }

    }

